<template>
  <div id="contant" style="width: 100vw; height: 100vh"></div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import * as d3 from "d3";
import Stats from "three/examples/jsm/libs/stats.module.js";
import { CSS3DRenderer, CSS3DObject } from "three/examples/jsm/renderers/CSS3DRenderer";

export default {
  name: "HelloWorld",
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      map: null,
      raycaster: null,
      mouse: new THREE.Vector2(),
      stats: null,
      lastPick: null,
      clock: null,
      projection1: null,
      geoJsonData: null,
      contant: null,
      css3dRenderer: null,
      labelElements: [],
      mapCenter: [112.73, 32.68] // 邓州默认中心
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.init();
    });
  },
  methods: {
    init() {
      this.createStats();
      this.createScene();
      this.createCamera();
      this.createLights();
      this.createRenderer();
      this.createCSS3DRenderer();
      this.loadGeoJsonData();
      this.setupControls();
      this.setupEventListeners();
      this.clock = new THREE.Clock();
      this.animate();
    },

    createStats() {
      try {
        this.stats = new Stats();
        this.stats.showPanel(0);
        this.stats.dom.style.position = "fixed";
        this.stats.dom.style.top = "0";
        this.stats.dom.style.left = "0";
        this.stats.dom.style.zIndex = "1000";
        document.body.appendChild(this.stats.dom);
      } catch (error) {
        console.error("初始化性能统计失败:", error);
      }
    },

    createCSS3DRenderer() {
      try {
        this.css3dRenderer = new CSS3DRenderer();
        this.css3dRenderer.setSize(window.innerWidth, window.innerHeight);
        this.css3dRenderer.domElement.style.position = "absolute";
        this.css3dRenderer.domElement.style.top = "0";
        this.css3dRenderer.domElement.style.left = "0";
        this.css3dRenderer.domElement.style.pointerEvents = "none";
        this.css3dRenderer.domElement.style.zIndex = "100";
        this.contant.parentNode.appendChild(this.css3dRenderer.domElement);
      } catch (error) {
        console.error("初始化CSS3D渲染器失败:", error);
      }
    },

    createScene() {
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0x000000);
      this.map = new THREE.Object3D();
    },

    createCamera() {
      this.contant = document.getElementById("contant");
      const width = this.contant.clientWidth;
      const height = this.contant.clientHeight;
      this.camera = new THREE.PerspectiveCamera(
        20,
        width / height,
        0.1,
        100000
      );
      this.camera.position.set(0, -1200, 1800);
    },

    createRenderer() {
      this.renderer = new THREE.WebGLRenderer({
        alpha: true,
        antialias: true
      });
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      this.renderer.setSize(this.contant.clientWidth, this.contant.clientHeight);
      this.contant.appendChild(this.renderer.domElement);
    },

    createLights() {
      const directionalLight = new THREE.DirectionalLight(0xffffff, 0.7);
      directionalLight.position.set(800, 1200, 1500);
      directionalLight.castShadow = true;
      directionalLight.shadow.mapSize.set(2048, 2048);
      directionalLight.shadow.camera.near = 0.5;
      directionalLight.shadow.camera.far = 8000;
      directionalLight.shadow.camera.left = -4000;
      directionalLight.shadow.camera.right = 4000;
      directionalLight.shadow.camera.top = 4000;
      directionalLight.shadow.camera.bottom = -4000;
      this.scene.add(directionalLight);

      const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
      this.scene.add(ambientLight);
    },

    loadGeoJsonData() {
      this.projection1 = d3
        .geoMercator()
        .center(this.mapCenter)
        .scale(25000)
        .translate([0, 0]);

      const loader = new THREE.FileLoader();
      loader.load(
        "/dengzhoushi.json",
        (data) => {
          this.geoJsonData = JSON.parse(data);
          console.log("地图数据加载成功，共", this.geoJsonData.features.length, "个区域");
          this.generateMap();
          this.autoFitMapToScreen();
        },
        undefined,
        (error) => {
          console.error("地图数据加载失败:", error);
        }
      );
    },

    generateMap() {
      if (!this.geoJsonData || !this.geoJsonData.features) {
        console.error("地图数据无效");
        return;
      }

      const features = this.geoJsonData.features;
      features.forEach((feature, featureIndex) => {
        const areaGroup = new THREE.Object3D();
        areaGroup.featureIndex = featureIndex;

        // 处理名称缺失
        const areaName = feature.properties?.name?.trim() || `未知区域${featureIndex + 1}`;
        areaGroup.properties = areaName;

        // 处理几何图形
        const coordinates = feature.geometry.coordinates;
        if (feature.geometry.type === "MultiPolygon") {
          this.handleMultiPolygon(coordinates, areaGroup, featureIndex);
        } else if (feature.geometry.type === "Polygon") {
          this.handlePolygon(coordinates, areaGroup, featureIndex);
        } else {
          console.warn(`区域${featureIndex + 1}：不支持的几何类型`, feature.geometry.type);
        }

        this.map.add(areaGroup);
      });

      this.scene.add(this.map);
      
      // 在所有区域创建完成后添加标签
      this.$nextTick(() => {
        this.addAllLabels();
        console.log("所有区域标签添加完成，共", this.labelElements.length, "个标签");
      });
    },

    handleMultiPolygon(coordinates, areaGroup, featureIndex) {
      coordinates.forEach((polygonGroup, groupIndex) => {
        if (!Array.isArray(polygonGroup) || polygonGroup.length === 0) {
          console.warn(`区域${featureIndex + 1}：空的MultiPolygon子组${groupIndex}`);
          return;
        }
        polygonGroup.forEach((polygon, polygonIndex) => {
          this.createAreaMeshAndLine(polygon, areaGroup, featureIndex, `Multi-${groupIndex}-${polygonIndex}`);
        });
      });
    },

    handlePolygon(coordinates, areaGroup, featureIndex) {
      coordinates.forEach((polygon, polygonIndex) => {
        if (!Array.isArray(polygon) || polygon.length < 3) {
          console.warn(`区域${featureIndex + 1}：无效Polygon（点数<3）`, polygon.length);
          return;
        }
        this.createAreaMeshAndLine(polygon, areaGroup, featureIndex, `Poly-${polygonIndex}`);
      });
    },

    createAreaMeshAndLine(polygon, parent, featureIndex, polyFlag) {
      try {
        if (!Array.isArray(polygon) || polygon.length < 3) {
          console.warn(`区域${featureIndex + 1}${polyFlag}：无效多边形（点数<3）`);
          return;
        }

        // 修改渐变参数以匹配指定的径向渐变
        const material = new THREE.ShaderMaterial({
          uniforms: {
            topColor: { value: new THREE.Color("#00469B") },
            bottomColor: { value: new THREE.Color("#001734") },
            gradientCenter: { value: new THREE.Vector2(0.08, 0.2) }, // 8% 20% 位置
            gradientRadius: { value: 0.89 }, // 89% 大小
            mixPoint: { value: 0.02 },
            specular: { value: new THREE.Color(0xffffff) },
            shininess: { value: 10.0 }
          },
          vertexShader: `
            varying vec2 vUv;
            varying vec3 vNormal;
            varying vec3 vPosition;
            void main() {
              vUv = uv;
              vNormal = normalize(normalMatrix * normal);
              vPosition = vec3(modelViewMatrix * vec4(position, 1.0));
              gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
          `,
          fragmentShader: `
            varying vec2 vUv;
            varying vec3 vNormal;
            varying vec3 vPosition;
            uniform vec3 topColor;
            uniform vec3 bottomColor;
            uniform vec2 gradientCenter;
            uniform float gradientRadius;
            uniform float mixPoint;
            uniform vec3 specular;
            uniform float shininess;
            
            void main() {
              // 计算径向渐变
              vec2 offsetUv = vUv - gradientCenter;
              float dist = length(offsetUv) / gradientRadius;
              float factor = smoothstep(mixPoint, 1.0, dist);
              vec3 diffuseColor = mix(topColor, bottomColor, factor);
              
              // 光照效果
              vec3 lightDir = normalize(vec3(0.5, 0.8, 1.0));
              vec3 viewDir = normalize(-vPosition);
              vec3 halfDir = normalize(lightDir + viewDir);
              float spec = pow(max(dot(vNormal, halfDir), 0.0), shininess);
              vec3 specularColor = spec * specular;
              
              gl_FragColor = vec4(diffuseColor + specularColor, 0.95);
            }
          `,
          transparent: true,
          side: THREE.FrontSide
        });

        const shape = new THREE.Shape();
        polygon.forEach((row, i) => {
          const [x, y] = this.projection1(row);
          if (i === 0) shape.moveTo(x, -y);
          else shape.lineTo(x, -y);
        });

        const extrudeSettings = {
          depth: 10,
          bevelEnabled: true,
          bevelSize: 1.2,
          bevelThickness: 1.0,
          bevelSegments: 3
        };
        const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
        geometry.computeVertexNormals();

        const mesh = new THREE.Mesh(geometry, material);
        mesh.properties = parent.properties;
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        mesh.name = `area-${parent.featureIndex}-mesh-${polyFlag}`;
        parent.add(mesh);

        const lineGeometry = new THREE.BufferGeometry();
        const pointsArray = polygon.map(row => {
          const [x, y] = this.projection1(row);
          return new THREE.Vector3(x, -y, extrudeSettings.depth + 0.5);
        });
        lineGeometry.setFromPoints(pointsArray);

        const lineMaterial = new THREE.LineBasicMaterial({
          color: 0xffffff,
          linewidth: 1.2
        });
        const line = new THREE.Line(lineGeometry, lineMaterial);
        line.name = `area-${parent.featureIndex}-line-${polyFlag}`;
        parent.add(line);
      } catch (error) {
        console.error(`区域${featureIndex + 1}${polyFlag}：创建失败`, error);
      }
    },

    // 新增方法：为所有区域添加标签
    addAllLabels() {
      this.map.children.forEach((areaGroup, index) => {
        this.addLabelToArea(areaGroup, index);
      });
    },

    // 重新实现的标签添加方法：使用几何中心计算
    addLabelToArea(areaGroup, areaIndex) {
      try {
        const areaName = areaGroup.properties;
        
        // 计算区域的几何中心
        const center = this.calculateGeometryCenter(areaGroup);
        if (!center) {
          console.warn(`区域${areaIndex}：无法计算中心点`);
          return;
        }

        const div = document.createElement('div');
        div.style.cssText = `
          color: #ffffff;
          font-family: "Microsoft YaHei", Arial, sans-serif;
          font-size: 12px;
          font-weight: bold;
          padding: 2px 6px;
          margin: 0;
          border: none;
          background: rgba(0, 0, 0, 0.6);
          pointer-events: none;
          white-space: nowrap;
          text-align: center;
          border-radius: 3px;
          text-shadow: 0 0 3px #000000, 
                       0 0 3px #000000;
          z-index: 10;
          transform: translate(-50%, -50%);
        `;
        div.textContent = areaName;
        div.dataset.areaIndex = areaIndex;

        const label = new CSS3DObject(div);
        label.position.copy(center);
        label.position.z += 15; // 提高标签高度，确保在区域上方
        label.name = `label-${areaIndex}`;
        label.areaName = areaName;

        this.scene.add(label);
        this.labelElements.push(label);
        
        console.log(`标签添加成功：${areaName} 位置:`, center);
      } catch (error) {
        console.error(`区域${areaIndex}：标签添加失败`, error);
      }
    },

    // 计算几何体中心点的新方法
    calculateGeometryCenter(areaGroup) {
      try {
        const boundingBox = new THREE.Box3();
        
        // 遍历区域组中的所有网格来计算包围盒
        areaGroup.traverse((child) => {
          if (child instanceof THREE.Mesh && child.geometry) {
            child.geometry.computeBoundingBox();
            const childBoundingBox = child.geometry.boundingBox.clone();
            
            // 应用网格的变换到包围盒
            child.updateMatrixWorld();
            childBoundingBox.applyMatrix4(child.matrixWorld);
            
            boundingBox.union(childBoundingBox);
          }
        });

        if (boundingBox.isEmpty()) {
          console.warn('无法计算区域包围盒');
          return null;
        }

        const center = new THREE.Vector3();
        boundingBox.getCenter(center);
        
        return center;
      } catch (error) {
        console.error('计算几何中心失败:', error);
        return null;
      }
    },

    autoFitMapToScreen() {
      const box3 = new THREE.Box3().setFromObject(this.map);
      const center = new THREE.Vector3();
      box3.getCenter(center);
      this.controls.target.copy(center);

      const size = new THREE.Vector3();
      box3.getSize(size);
      const diagonal = size.length();
      const cameraDistance = diagonal / (2 * Math.tan(Math.PI * this.camera.fov / 360)) * 1.1;
      this.camera.position.set(center.x, center.y - diagonal * 0.4, center.z + cameraDistance);
      this.controls.update();

      // 验证标签位置
      this.checkLabelsCentering();
    },

    checkLabelsCentering() {
      console.log("=== 标签位置验证 ===");
      this.labelElements.forEach((label, index) => {
        const worldPosition = new THREE.Vector3();
        label.getWorldPosition(worldPosition);
        console.log(`标签${index + 1}（${label.areaName}）：世界坐标`, worldPosition);
      });
    },

    setupControls() {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.15;
      this.controls.minDistance = 800;
      this.controls.maxDistance = 4000;
      this.controls.maxPolarAngle = Math.PI * 0.7;
      this.controls.update();
    },

    setupEventListeners() {
      this.raycaster = new THREE.Raycaster();
      window.addEventListener("resize", this.onWindowResize.bind(this));
      this.renderer.domElement.addEventListener("click", this.onRay.bind(this));
    },

    onWindowResize() {
      const width = this.contant.clientWidth;
      const height = this.contant.clientHeight;
      this.camera.aspect = width / height;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(width, height);
      if (this.css3dRenderer) {
        this.css3dRenderer.setSize(width, height);
      }
      if (this.map) this.autoFitMapToScreen();
    },

    onRay(event) {
      const pickPosition = this.setPickPosition(event);
      this.raycaster.setFromCamera(pickPosition, this.camera);
      const intersects = this.raycaster.intersectObjects([this.map], true);

      if (this.lastPick && this.lastPick.object.material.uniforms) {
        this.lastPick.object.material.uniforms.topColor.value.set("#00469B");
      }

      if (intersects.length > 0) {
        const target = intersects[0];
        if (target.object.properties && target.object.material.uniforms) {
          target.object.material.uniforms.topColor.value.set("#ff6b35");
          this.lastPick = target;
          console.log("选中区域:", target.object.properties);
        }
      } else {
        this.lastPick = null;
      }
    },

    setPickPosition(event) {
      const rect = this.renderer.domElement.getBoundingClientRect();
      return {
        x: ((event.clientX - rect.left) / rect.width) * 2 - 1,
        y: -((event.clientY - rect.top) / rect.height) * 2 + 1
      };
    },

    animate() {
      requestAnimationFrame(this.animate.bind(this));
      if (this.controls) this.controls.update();
      if (this.stats) this.stats.update();
      this.render();
    },

    render() {
      this.renderer.render(this.scene, this.camera);
      if (this.css3dRenderer) {
        this.css3dRenderer.render(this.scene, this.camera);
      }
    }
  },

  beforeDestroy() {
    // 清理标签
    this.labelElements.forEach(label => {
      if (label.element && label.element.parentElement) {
        label.element.parentElement.removeChild(label.element);
      }
      this.scene.remove(label);
    });
    this.labelElements = [];

    // 清理其他资源
    if (this.controls) this.controls.dispose();
    if (this.renderer) this.renderer.dispose();
    if (this.css3dRenderer) {
      this.css3dRenderer.dispose();
      if (this.css3dRenderer.domElement.parentElement) {
        this.css3dRenderer.domElement.parentElement.removeChild(this.css3dRenderer.domElement);
      }
    }
    if (this.stats && this.stats.dom && this.stats.dom.parentElement) {
      this.stats.dom.parentElement.removeChild(this.stats.dom);
    }

    // 移除事件监听
    window.removeEventListener("resize", this.onWindowResize.bind(this));
    if (this.renderer && this.renderer.domElement) {
      this.renderer.domElement.removeEventListener("click", this.onRay.bind(this));
    }
  }
};
</script>

<style scoped>
#contant {
  margin: 0;
  padding: 0;
  overflow: hidden;
  position: relative;
}
</style>